﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace iopt.solvency.pillarone.core
{
    public interface IComponent
    {
        void Execute(IComputeContext ComputeContext, IDataContext DataContext);
    }

    public interface ITable : IQueryable<IRow>
    {
        string Name { get; }

        IRow Add(string setkey, string key);
        bool Delete(IRow row);
        bool Delete(string setkey, string key);

        IRow this[string setkey, string key] { get; }

        IEnumerable<string> SetList { get; }
        IEnumerable<string> ColumnList { get; }

        void Persist();
    }

    public interface ITableFactory : IDictionary<string, ITable>
    {
        ITable CreateTable(string name);
    }

    public interface IRow
    {
        ITable Row { get; }

        string Key { get; }
        string SetKey { get; }

        object this[string column] { get; set; }
    }
   
    public interface IVector
    {
        double this[int row] { get ; }

        int Count { get; }
    }
    public interface IMatrix
    {
        double this[int row, int column] { get; }

        int RowCount { get; }

        int ColumnCount { get; }
    }

    public interface IInputArgument<T>
    {
        T Get();
    }
    public interface IOutputArgument<T>
    {
        void Set(Lazy<T> lazyvalue);
        void Set(T value);
    }

    public interface IComputeContext
    {
        int IterationIndex { get; }
        int PeriodIndex { get; }

        int MaxIteration { get; }
        int MaxPeriod { get; }

        ComputeStatus Status { get; }
    }

    public enum ComputeStatus
    {
        SimulationStart,
        SimulationEnd,
        Period,
        IterationStart,
        IterationEnd
    }

    public interface IDataContext
    {
        IModelPointSet ModelPointSet { get; }

        IParameterSet ParameterSet { get; }

        IAccountSet AccountSet { get; }

    }
    public interface IModelPointSet
    {
        IEnumerable<IField> Fields { get; }

        IEnumerable<IField> KeyFields { get; }

        IQueryable<IModelPoint> ModelPoints { get; }

        IModelPoint GetModelPoint(ISegment key);


        int Count { get; }
    }
    public interface IModelPoint
    {
        ISegment Key { get; }

        object GetField(string fieldName);

        object GetField(IField field);
    }
    public interface IParameterSet
    {
        IReadOnlyDictionary<string, IParameter> Items { get; }
    }
    public interface IParameter
    {
        string Name { get; }

        object Get();

        object Get(IModelPoint ModelPoint);

        object Get(ISegment Segment);
    }
    public interface IAccount
    {
        string Name { get; }

        IReadOnlyDictionary<string, IAccountItem> Items { get; }
    }
    public interface IAccountItem
    {
        string Name { get; }

        double? Value { get; set; }
    }
    public interface IAccountSet
    {
        ISegment RootSegment { get; }

        IReadOnlyDictionary<string, IAccount> GetAccounts();

        IReadOnlyDictionary<string, IAccount> GetAccounts(ISegment Segment);
    }
    public interface ISegment : IEnumerable<ISegment>, IEquatable<ISegment>
    {
        bool HasChildren { get; }

        IReadOnlyDictionary<IField, object> Values { get; }
    }
    public interface IField
    {
        string Name { get; }

        System.TypeCode Type { get; }
    }
    public interface IReadOnlyDictionary<K, V> : IEnumerable<KeyValuePair<K, V>>
    {
        bool Contains(K key);
        V Get(K key);
        bool TryGet(K key, out V value);

        int Count { get; }
        IEnumerable<K> Keys { get; }
        IEnumerable<V> Values { get; }
    }
}
